#include "state.h"


State::State(int nq)
    : n(nq)
{
    l = 1L << n;
    vec = new complexd [l];
}

State::State(const State &obj)
{
    n = obj.n;
    l = obj.l;
    vec = new complexd [l];
    for (long long i = 0; i < l; i++)
        vec[i] = obj.vec[i];
}

State::~State()
{
    delete [] vec;
}

void State::intentionalFill(int nt, long long lt, complexd* new_vec)
{
    n = nt;
    l = lt;
    for (long long i = 0; i < l; i++)
        vec[i] = new_vec[i];
}

void State::doConversion(Conversion &con, int k)
{
    complexd* vec_new = new complexd [l];
    long long i;
#pragma omp parallel for private(i) schedule (guided,10)
    for (i = 0; i < l; i++)
       vec_new[i] = con[k_bit_of_i(i,k,n)][0]*vec[set_k_bit_i_0(i,k,n)]
                  + con[k_bit_of_i(i,k,n)][1]*vec[set_k_bit_i_1(i,k,n)];

    delete [] vec;
    vec = vec_new;
}

void State::norma()
{
    long double sum = 0;
    long long i;
#pragma omp parallel private(i)
    {
#pragma omp for reduction( + : sum) schedule(guided,10)
    for (i = 0; i < l; i++)
        sum += abs(vec[i]) * abs(vec[i]);
#pragma omp single
    {
        sum = sqrt(sum);
        if (sum == 0)
            sum = 1.0;
    }
//HOW??????
#pragma omp for schedule(guided,10)
    for (i = 0; i < l; i++)
        vec[i] = vec[i] / (double)sum;
    }
}

void State::randomFill()
{
    for (long long ln = 0; ln < l; ln++)
        vec[ln] = myrandom();
}


State State::operator=(State state)
{
    n = state.n;
    l = state.l;
    vec = new complexd [l];
    for (int i = 0; i < l; i++)
        vec[i] = state.vec[i];
    return *this;
}

bool State::operator==(State state)
{
    if (n != state.n || l != state.l)
        return false;
    for (int i = 0; i < l; i++)
        if (vec[i] != state.vec[i])
            return false;
    return true;
}

bool State::operator!=(State state)
{
    if (n != state.n || l != state.l)
        return true;
    for (int i = 0; i < l; i++)
        if (vec[i] != state.vec[i])
            return true;
    return false;
}


int State::getDimension()
{
    return n;
}

long long State::getLong()
{
    return l;
}

complexd* State::getVector()
{
    return vec;
}


ostream& operator<<(ostream &stream, State &state)
{
    for (long long lt = 0; lt < state.getLong(); lt++)
        cout << state.getVector()[lt] << " ";
    cout << endl;
    return stream;
}

